/*
 * Copyright (c) 2020 Fraunhofer FOKUS and others. All rights reserved.
 *
 * See the NOTICE file(s) distributed with this work for additional
 * information regarding copyright ownership.
 *
 * This program and the accompanying materials are made available under the
 * terms of the Eclipse Public License 2.0 which is available at
 * http://www.eclipse.org/legal/epl-2.0
 *
 * SPDX-License-Identifier: EPL-2.0
 *
 * Contact: mosaic@fokus.fraunhofer.de
 */
package org.eclipse.mosaic.fed.carla.clojure.commands;

import libpython_clj2.java_api;
import org.eclipse.mosaic.fed.carla.clojure.AbstractCarlaCommand;
import org.eclipse.mosaic.fed.carla.clojure.ClojureCarlaConnection;

import java.util.Map;

/**
 * This class represents the carla command which allows to set the simulation step.
 */
public class SimulationSimulateStep extends AbstractCarlaCommand {

    public SimulationSimulateStep() {
        super();
    }

    public Void execute(ClojureCarlaConnection connection) {
        try (AutoCloseable locker = java_api.GILLocker()) {
            Object carlaWorld = connection.carlaWorld;
            Object tick = java_api.getAttr(carlaWorld, "tick");
            java_api.call(tick);

            // update connection: spawned/destroyed/active
            Map global = java_api.runStringAsFile(
                    "\n" +
                            "def get_current_actors(carla_world): \n" +
                            "        current_actors = set(\n" +
                            "            [vehicle.id for vehicle in carla_world.get_actors().filter('vehicle.*')])\n" +
                            "        return list(current_actors)\n" +
                            "def get_spawned_actors(current_actors, active_actors): \n" +
                            "        spawned_actors = set(current_actors).difference(active_actors)\n" +
                            "        return list(spawned_actors)\n" +
                            "def get_destroyed_actors(current_actors, active_actors): \n" +
                            "        destroyed_actors = set(active_actors).difference(current_actors)\n" +
                            "        return list(destroyed_actors)\n"
            );
            Object getCurrentActors = global.get("get_current_actors");
            Object getSpawnedActors = global.get("get_spawned_actors");
            Object getDestroyedActors = global.get("get_destroyed_actors");

            Object currentActors = java_api.call(getCurrentActors, connection.carlaWorld);
            connection.spawnedCarlaActors = java_api.call(getSpawnedActors, currentActors, connection.activeActors);
            connection.destroyedActors = java_api.call(getDestroyedActors, currentActors, connection.activeActors);
            connection.activeActors = currentActors;
        } catch (Exception e) {
            throw new RuntimeException(e);
        }
        return null;
    }
}
